<?php

namespace Modules\Wechat\Model\Data\OfficialAccount;


use Base\Exception\Data as Exception;
use Modules\Wechat\Model\Dao\Db\WcOaOAuth;
use Modules\Wechat\Model\Data\Abstraction as DataAbstraction;

/**
 * 用户OAuth数据
 *
 * @package Modules\Wechat\Model\Data\OfficialAccount
 */
class OAuth extends DataAbstraction
{

    protected $expire_safety = 15;


    public function setExpireSafety($second = 15)
    {
        $this->expire_safety = intval($second);
        return $this;
    }

    public function getExpireSafety()
    {
        return $this->expire_safety;
    }

    public function getExpiresOn($expires_in, $curr_timestamp = 0)
    {
        $curr_timestamp = $curr_timestamp ? intval($curr_timestamp) : time();
        return $expires_in + $curr_timestamp - $this->getExpireSafety();
    }

    public function exists($official_account, $open_id)
    {
        $WcOaOauth = new WcOaOAuth();
        $pk        = $WcOaOauth->generatePk($official_account, $open_id);
        return $WcOaOauth->readByPk($pk) ?: [];
    }

    /**
     * 保存用户OAuth数据
     *
     * @param             $official_account
     * @param string      $open_id
     * @param string|null $access_token
     * @param string|null $expires_in
     * @param string|null $refresh_token
     * @param string|null $union_id
     * @param string|null $scope
     *
     * @return bool|int
     * @throws Exception
     */
    public function save(
        $official_account,
        $open_id,
        $access_token = null,
        $expires_in = null,
        $refresh_token = null,
        $union_id = null,
        $scope = null
    ) {
        if (empty($open_id)) {
            throw new Exception('OpenId不能为空');
        }

        $time      = time();
        $WcOaOAuth = new WcOaOAuth;

        if ($official_account && $open_id) {
            $data[$WcOaOAuth->getPkField()] = $WcOaOAuth->generatePk($official_account, $open_id);
        }

        $data['official_account'] = $official_account;
        $data['open_id']          = $open_id;
        $data['access_token']     = $access_token;
        $data['expires_in']       = $expires_in;
        $data['refresh_token']    = $refresh_token;
        $data['union_id']         = $union_id;
        $data['expires_on']       = is_null($expires_in) ? null : $this->getExpiresOn($expires_in);
        $data['scope']            = $scope;

        if ($exists = $this->exists($official_account, $open_id)) {
            $data['utime'] = $time;
            return $WcOaOAuth->setProperties($data, true)->updateByPk();
        }
        $data['open_id'] = $open_id;
        $data['ctime']   = $time;
        return $WcOaOAuth->setProperties($data, true)->create(true);
    }

    public function getByUnionId($union_id)
    {
        return (new WcOaOAuth)->setProperty('union_id', $union_id)->readRow() ?: [];
    }

    public function isInAuthorizationState($official_account, $open_id, $return_id = false)
    {
        if ($exists = $this->exists($official_account, $open_id)) {
            if ($exists['expires_on'] > time()) {
                return $return_id
                    ? ['open_id' => $exists['open_id'], 'union_id' => $exists['union_id']]
                    : true;
            }
        }
        return $return_id ? [] : false;
    }

    public function isInAuthorizationStateByUnionId($union_id)
    {
        if ($exists = $this->getByUnionId($union_id)) {
            return $exists['expires_on'] > time();
        }
        return false;
    }

    protected function init()
    {
        return $this;
    }

}